import PageTable from '@components/page_table';
import {Button, Form, message, Modal} from "antd";
import moment from "moment";
import MyForm from './form.jsx';
import {api_module_getModuleTableInfo} from "@utils/api.js";
import {BASE_URL} from "@utils/constants.js";
import {request} from "@utils/request.js";
import React from "react";
import {
    ProFormCascader,
    ProFormDateMonthRangePicker,
    ProFormDatePicker,
    ProFormDateRangePicker,
    ProFormDateTimePicker,
    ProFormDigit,
    ProFormSelect,
    ProFormSwitch,
    ProFormText,
    ProFormTextArea
} from "@ant-design/pro-components";
import Editor from "@components/editor/index.jsx";
import Upload_img from "@components/upload_img/index.jsx";
import Upload_file from "@components/upload_file/index.jsx";

const createOp = 'c'
const readOp = 'r'
const updateOp = 'u'
const deleteOp = 'd'
const createName = '新增'
const readName = '列表'
const updateName = '修改'
const deleteName = '删除'
const hideField = ['id', 'update_time', 'create_user_id', 'update_user_id', 'pageIndex', 'pageSize']
const columnsIndex = []

export const getForm = async (info) => {
    let args = JSON.parse(JSON.stringify(info.valid));
    return await formItemType[info.type](info, {
        key: info.prop,
        name: info.prop,
        label: info.label,
        rules: [{required: args.required}],
        width: '100%',
        ...args
    })
}
const formItemType = {
    img: async (_, args) => <Form.Item {...args}><Upload_img/></Form.Item>,
    file: async (_, args) => <Form.Item {...args}><Upload_file/></Form.Item>,
    text: async (_, args) => <ProFormText {...args}/>,
    number: async (_, args) => <ProFormDigit {...args} min={0}/>,
    editor: async (_, args) => <Form.Item {...args} shouldUpdate><Editor/></Form.Item>,
    select: async ({valid}, args) => {
        let select = valid?.select
        if (typeof select === 'string') select = await request(select)
        let options = select || [];
        let multiple = eval(valid?.multiple) || false;
        return <ProFormSelect {...args} mode={multiple ? 'tags' : 'single'} options={options}/>
    },
    cascader: async ({valid}, args) => {
        let cascader = valid?.cascader
        if (typeof cascader === 'string') cascader = await request(cascader)
        let options = cascader || [];
        let multiple = eval(valid?.multiple) || false;
        return <ProFormCascader {...args} fieldProps={{options, multiple}}/>
    },
    date: async (_, args) => <ProFormDatePicker {...args}/>,
    dateRange: async (_, args) => <ProFormDateRangePicker {...args}/>,
    dateTime: async (_, args) => <ProFormDateTimePicker {...args}/>,
    dateTimeRange: async (_, args) => <ProFormDateRangePicker {...args}/>,
    dateMonthRange: async (_, args) => <ProFormDateMonthRangePicker {...args}/>,
    switch: async (_, args) => <ProFormSwitch {...args} initialValue={true}/>,
    textArea: async (_, args) => <ProFormTextArea {...args}/>,
    other: (_, args) => <ProFormText {...args}/>
}

const getParamInfo = (key, label, valid) => {
    let arr = key.split('-')
    let prop = arr[0]
    let type = arr[1] || 'other'
    valid = valid[arr[0]] || {}
    let required = eval(valid[arr[0]]?.required || false);
    return {type, prop, valid}
}
const endWithFieldDom = (row, name, value) => {
    if (name + '-render' in row) return <div dangerouslySetInnerHTML={{__html: row[name + '-render']}}/>
    else if (value == null) return '-'
    if (name.endsWith("img")) return <img src={value?.startsWith('http') ? value : BASE_URL + value} alt="暂无图片"
                                          style={{width: 28}}/>
    else if (name.endsWith("time")) return moment(value).format('YYYY-MM-DD HH:mm:ss')
    else if (name.endsWith("file")) return <a download={value?.split('/').pop()}
                                              href={value?.startsWith('http') ? value : BASE_URL + value}>{value.split('/').pop()}</a>
    else return value
}
export default () => {
    const actionRef = useRef();
    const [open, setOpen] = useState(false);
    const [form, setForm] = useState({});
    const [operation, setOperation] = useState({});
    const [columns, setColumns] = useState([]);
    const [pagination, setPagination] = useState(false);
    const getColumn = async (e, operation) => {
        let hide = false
        if (e.des.endsWith('|')) {
            hide = true
            e.des = e.des.slice(0, -1)
        }
        columnsIndex.push(e.name)
        return {
            title: e.des,
            dataIndex: e.name,
            align: 'center',
            valueType: 'text',
            hideInTable: hide,
            search: !!operation[readOp]?.req[e.name],
            render: (_, row) => endWithFieldDom(row, e.name, row[e.name])
        }
    }

    const getSearch = async (e, operation) => {
        let key = e
        let label = operation[readOp].req[e]
        let valid = operation[readOp]?.valid
        let info = getParamInfo(e, label, valid)
        if (info === undefined) return null
        let dom = await getForm(info)
        return {
            title: label,
            dataIndex: info.prop,
            valueType: info.type,
            search: true,
            hideInTable: true,
            renderFormItem: () => dom,
        }
    }
    const reload = () => actionRef?.current?.reload && actionRef?.current?.reload();
    const init = async () => {
        let module = JSON.parse(sessionStorage.getItem(location.pathname));
        let info = JSON.parse(sessionStorage.getItem("crud_module_" + location.pathname));
        if (!info) {
            info = await request(api_module_getModuleTableInfo, {path: module.path})
            sessionStorage.setItem("crud_module_" + location.pathname, JSON.stringify(info));
        }
        let {
            tableName,
            tableInfo,
            permissionInfo
        } = info
        //获取操作权限
        let opera = {}
        tableInfo.sort((a, b) => a.sort - b.sort)
        let operationStr = tableName.split('-')[1]
        if (operationStr) [...operationStr].forEach(e => opera[e] = true)
        else [createOp, updateOp, deleteOp].forEach(e => opera[e] = true)
        permissionInfo.forEach(e => {
            if (e.name === createName) opera[createOp] && (opera[createOp] = e)
            else if (e.name === readName) opera[readOp] = Object.assign(e, {columns: tableInfo})
            else if (e.name === updateName) opera[updateOp] && (opera[updateOp] = e)
            else if (e.name === deleteName) opera[deleteOp] && (opera[deleteOp] = e)
        })
        if (opera[readOp]?.url?.startsWith('pt/')) opera[readOp].url = opera[readOp].url.replace('pt/', '')
        if (opera[createOp]?.url?.startsWith('pt/')) opera[createOp].url = opera[createOp].url.replace('pt/', '')
        if (opera[updateOp]?.url?.startsWith('pt/')) opera[updateOp].url = opera[updateOp].url.replace('pt/', '')
        if (opera[deleteOp]?.url?.startsWith('pt/')) opera[deleteOp].url = opera[deleteOp].url.replace('pt/', '')
        setOperation(opera)
        //获取表格列信息
        const columns = await Promise.all([
            ...opera[readOp].columns.filter(e => !hideField.includes(e.name)).map(async (e) => await getColumn(e, opera)),
            ...Object.keys(opera[readOp].req).filter(e => !hideField.includes(e) && !columnsIndex.includes(e)).map(async (e) => await getSearch(e, opera))
        ]);
        setColumns(columns)
    }
    useEffect(() => {
        init().then();
    }, []);
    return (
        <>
            {operation[readOp] && <PageTable
                search={{}}
                actionRef={actionRef}
                actions={[
                    !!operation[createOp] && <Button
                        type="primary"
                        key="customized"
                        onClick={() => {
                            setForm({})
                            setOpen(true)
                        }}
                    >
                        新增
                    </Button>
                ]}
                columns={columns}
                pagination={pagination}
                operation={!!operation[updateOp] || !!operation[deleteOp] ? (_, item) => [
                    !!operation[updateOp] && <a
                        key="edit"
                        onClick={() => {
                            setOpen(true);
                            setForm(item);
                        }}
                    >
                        修改
                    </a>,
                    !!operation[deleteOp] && <a
                        key="del"
                        onClick={async () => {
                            Modal.confirm({
                                title: '提醒',
                                content: `确认删除该项吗？`,
                                okText: '确认',
                                cancelText: '取消',
                                onOk: async () => {
                                    await request(operation[deleteOp].url, {id: item.id});
                                    message.success('删除成功');
                                    await reload();
                                },
                            });
                        }}
                    >
                        删除
                    </a>
                ] : false}
                request={async (params) => {
                    const data = {
                        ...params,
                    };
                    const body = await request(operation[readOp].url, data);
                    let list = body?.list || [];
                    if (body?.total && body?.total > 0) setPagination(true)
                    return {
                        data: list || [],
                        success: true,
                        total: body?.total || 0
                    };
                }}
            />}
            {open && <MyForm
                operation={form.id ? operation[updateOp] : operation[createOp]}
                detail={form}
                onCancel={() => setOpen(false)}
                onOk={async () => {
                    setOpen(false);
                    await reload();
                }}
            />

            }

        </>
    );
}